##Sisaba is a python script backups complete directory structures to a samba share. 
##Once per month it copies the whole diretory structure with contents. 
##If there is already a full backup for the current month it only backups new or edited files.

##Author: Bruno Hautzenberger 2010

##
##
##This program is free software: you can redistribute it and/or modify
##it under the terms of the GNU General Public License as published by
##the Free Software Foundation, either version 3 of the License, or
##(at your option) any later version.
##
##This program is distributed in the hope that it will be useful,
##but WITHOUT ANY WARRANTY; without even the implied warranty of
##MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
##GNU General Public License for more details.
##
##You should have received a copy of the GNU General Public License
##along with this program.  If not, see <http://www.gnu.org/licenses/>.

import os
import shutil
import time
import md5



## EDIT THESE VALUES ##
sambaShare = '//192.168.0.10/backup' #ip + name of your samba share
sambaUser = 'myUserNAme' #your samba user
sambaPassword = 'secret' #your samba password
backupMountPoint = "/backup" #the mountpoint of the backup on your system
backupPath = backupMountPoint + "/myLaptop" #the path inside the mountpoint
configFile = "/opt/sisaba/backup.conf" #the config file
logfile = "/opt/sisaba/backup.log" #the logfile

## YOU SHOULD NOT HAVE TO EDIT ANYTHING AFTER THIS LINE! ## 


currentBackUpDir = ""
currentBasePath = ""
fullBackUp = False
conf = {}
olderBackups = []
log = open(logfile,'w')

def readConfig():
	confFile = open(configFile)
	c = confFile.readline()
	while c.strip() != "":
		print c
		cKey, cVal = c.split("=")
		conf[cKey.strip()] = cVal.strip()
		c = confFile.readline()


def scanDirectory(basePath):
	arglist = []
	Log("\nBackup: " + basePath)
	print "Backup: " + basePath
	os.path.walk(basePath,scanDirectoryCB,arglist)

def scanDirectoryCB(arg, dirname, fnames ):
	dir = dirname[len(currentBasePath):len(dirname)]

	if fullBackUp == False:
		backupdir = backupPath + "/" + str(year) + "_" + str(month) + "_" + str(day) + dir
	else:
		backupdir = backupPath + "/" + dir
	
	if not os.path.exists(backupdir):
		os.mkdir(backupdir)
		Log("Creating Backup Directory: " + backupdir)

	print dirname
	for file in fnames:
		print file
		if not os.path.isdir(dirname + "/" + file):
			backupfile = backupdir + "/" + file
			origFile = dirname + "/" + file
			if doBackupForFile(origFile,dir+backupfile[len(backupdir):len(backupfile)]) or fullBackUp == True:
				shutil.copy2(origFile, backupdir)
				Log("Backup for " + origFile + " done!")

def doBackupForFile(origFile,f):
	Log("Checking if there is already a Backupf for file " + origFile)
	
	for path in olderBackups:
		backupfile = path + f
		if os.path.exists(backupfile):
			Log("File " + origFile + " exists in " + backupfile)
			Log("Checking if " + origFile + " is the same as " + backupfile)
			fb = open(backupfile,'rb')
			fo = open(origFile,'rb')
			if fb.read() == fo.read():
				Log("There is already a Backup for file " + origFile + " -> " + backupfile)
				return False
	return True
			

def Log(msg):
	log.write(msg + "\n")	
	log.flush()

def getOlderBackups():
	oldBackUp = backupPath + "/FULL" 
	olderBackups.append(oldBackUp)

	day = 1
	year = time.localtime().tm_year
	month = time.localtime().tm_mon
	while day < 32:
		oldBackUp = backupPath + "/" + str(year) + "_" + str(month) + "_" + str(day)
		if os.path.exists(oldBackUp):
			Log("Found Backup Directory " + oldBackUp)
			olderBackups.append(oldBackUp)
		day = day + 1
			

def doBackup():
	if fullBackUp == False:
		backupdir = backupPath + "/" + str(year) + "_" + str(month) + "_" + str(day)
	else:
		backupdir = backupPath

	for path in conf['DIRS'].split(";"):
		cDir = backupdir
		for directory in path.split("/"):
			if directory.strip() != "":
				cDir = cDir + "/" + directory
				try:
					os.mkdir(cDir)
				except:
					Log(cDir + " already exists!")
		currentBasePath = path
		scanDirectory(path)

#main routine
Log("\nSTARTING TO BACKUP") 
print "Starting backup..."

os.system('sudo smbmount ' + sambaShare + ' ' + backupMountPoint + ' -o username=' + sambaUser + ',password=' + sambaPassword + ',uid=1000,mask=000')

readConfig()

#getDate
year = time.localtime().tm_year
month = time.localtime().tm_mon
day = time.localtime().tm_mday

#create directory for this month
backupPath = backupPath + "/" + str(year) + "_" + str(month)

try:

	if not os.path.exists(backupPath):
		os.mkdir(backupPath)
		backupPath = backupPath + "/" + "FULL"
		os.mkdir(backupPath)
		Log("Directory created: " + backupPath)
		Log("Doing a Full-Backup!")
		fullBackUp = True
	else:
		getOlderBackups()
		thisPath = backupPath + "/" + str(year) + "_" + str(month) + "_" + str(day)
		os.mkdir(thisPath)
		Log("Directory created: " + thisPath)
		Log("Doing an incremental backup!")
		fullBackUp = False
	
	doBackup()
except Exception as ex:
	print ex
	Log(str(ex))
	

log.close()

os.system("chmod 755 " + logfile)

os.system('sudo umount ' + backupMountPoint)


	


		

